import { ref, type Ref } from 'vue'

interface ListOptionsRes<T> {
  pageCount: number
  pageNo: number
  pageSize: number
  rows: T[]
  total: number
}

interface ListServiceParams {
  page: number
  rows: number
}

type ListService<R> = (params: ListServiceParams) => Promise<ListOptionsRes<R>>

interface Options {
  page?: number
  rows?: number
  onSuccess?: () => void
}

type Status = 'loading' | 'finished'

export function usePageList<T>(service: ListService<T>, options: Options = {}) {
  const page = ref(options.page ?? 1)
  const rows = ref(options.rows ?? 20)
  const loading = ref(false)
  const status = ref<Status>('loading')
  const total = ref(0)

  const list: Ref<T[]> = ref([])
  const getList = async () => {
    try {
      status.value = 'loading'
      loading.value = true
      const res = await service({ page: page.value, rows: rows.value })
      if (!res.rows)
        return (status.value = 'finished')
      total.value = res.total
      if (list.value.length < res.total) {
        list.value.push(...res.rows)
      }
      status.value = list.value.length >= res.total ? 'finished' : 'loading'
      page.value = list.value.length >= res.total ? page.value : page.value + 1
      options.onSuccess && options.onSuccess()
      uni.stopPullDownRefresh()
    }
    catch {
      status.value = 'loading'
    }
    finally {
      loading.value = false
    }
  }

  const search = () => {
    list.value = []
    page.value = options.page ?? 1
    getList()
  }

  onPullDownRefresh(() => {
    search()
  })

  return {
    page,
    rows,
    loading,
    status,
    total,
    list,
    getList,
    search,
  }
}
